package com.chengwei.ch.busdemo.hermes.modules

import android.content.Context
import com.chengwei.ch.busdemo.hermes.contract.*
import com.chengwei.ch.busdemo.utils.AppUtil
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*
import java.nio.charset.Charset

/**
 * MQTT推送客户端实现
 * @author zdk
 * @date 2019/12/21
 */
class HermesImpl : Hermes {
    /** 日志标签 */
    private var mTag = AppUtil.TAG
    /** mqtt服务端 */
    private var mMqttClient: MqttAndroidClient? = null
    /** mqtt连接配置 */
    private var mMqttConnectOptions: MqttConnectOptions? = null
    /** 订阅监听器 */
    private var mOnSubscribeListener: OnSubscribeListener? = null
    /** 退订监听器 */
    private var mOnUnSubscribeListener: OnUnSubscribeListener? = null
    /** 连接监听器 */
    private var mOnConnectListener: OnConnectListener? = null
    /** 发送监听器 */
    private var mOnSendListener: OnSendListener? = null
    /** 断开监听器 */
    private var mOnDisconnectListener: OnDisconnectListener? = null
    /** 订阅主题列表 */
    private var mSubTopics: List<String>? = null

    override fun init(context: Context?, url: String, clientId: String?, options: MqttConnectOptions?) {
        mMqttClient = MqttAndroidClient(context, url, clientId)
        mMqttConnectOptions = options
        mMqttClient?.setCallback(mMqttCallbackExtended)
        if (mMqttConnectOptions == null) {
            mMqttConnectOptions = MqttConnectOptions()
            mMqttConnectOptions?.isAutomaticReconnect = true
            //isCleanSession -> true,回话到期间隔为0，false表示回话到期间隔为7200
            mMqttConnectOptions?.isCleanSession = true
        }
    }

    /** mqtt接口回调 */
    private val mMqttCallbackExtended = object : MqttCallbackExtended {

        override fun connectComplete(reconnect: Boolean, serverURI: String?) {
            if (reconnect) {
                PrintLog.d(mTag, "mqtt重新连接上服务地址 : $serverURI")
                // ToastUtils.showShort("mqtt重新连接上服务地址")
                //  subscribeTopic()// 重新连接上需要再次订阅主题
            } else {
                PrintLog.d(mTag, "mqtt连接上服务地址 : $serverURI")
                //ToastUtils.showShort("mqtt连接上服务地址")
            }
            mOnConnectListener?.onConnectComplete(reconnect)
        }

        override fun messageArrived(topic: String?, message: MqttMessage?) {
            if (message == null) {
                PrintLog.i(mTag, "数据到达 : null")
                return
            }
            // 后台推送的消息到达客户端
            val msg = String(message.payload, Charset.forName("UTF-8"))
            // PrintLog.i(mTag, "数据到达 : $msg")
            mOnSubscribeListener?.onMsgArrived(topic ?: "", msg)
        }

        override fun connectionLost(cause: Throwable?) {
            val defCause = cause ?: RuntimeException("mqtt connection lost")
            mOnConnectListener?.onConnectionLost(defCause)// 连接丢失
        }

        override fun deliveryComplete(token: IMqttDeliveryToken?) {}
    }

    override fun setSubTopic(topics: List<String>?) {
        mSubTopics = topics
    }

    override fun setOnSubscribeListener(listener: OnSubscribeListener?) {
        mOnSubscribeListener = listener
    }

    override fun setOnUnSubscribeListener(listener: OnUnSubscribeListener?) {
        mOnUnSubscribeListener = listener
    }

    override fun setOnConnectListener(listener: OnConnectListener?) {
        mOnConnectListener = listener
    }

    override fun setOnSendListener(listener: OnSendListener?) {
        mOnSendListener = listener
    }

    override fun setOnDisconnectListener(listener: OnDisconnectListener?) {
        mOnDisconnectListener = listener
    }

    override fun sendTopic(topic: String, content: String) {
        try {
            val message = MqttMessage()
            message.payload = content.toByteArray()
            mMqttClient?.publish(topic, message, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    PrintLog.i(mTag, "$topic  --- 数据发送成功 : $content")
                    mOnSendListener?.onSendComplete(topic, content)
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    PrintLog.i(mTag, "$topic  --- 数据发送失败 : $content")
                    mOnSendListener?.onSendComplete(topic, content)
                }

            })
        } catch (e: Exception) {
            e.printStackTrace()
            mOnSendListener?.onSendFailure(topic, e)
            PrintLog.e(mTag, "$topic  --- 数据发送失败 : ${e.cause}")
        }
    }

    override fun connect() {
        try {
            if (isConnected()) {
                return
            }
            mMqttClient?.connect(mMqttConnectOptions, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    val disconnectedBufferOptions = DisconnectedBufferOptions()
                    //开启
                    disconnectedBufferOptions.isBufferEnabled = true
                    //离线后最多缓存100调
                    disconnectedBufferOptions.bufferSize = 100
                    //不一直持续留存
                    disconnectedBufferOptions.isPersistBuffer = false
                    //删除旧消息
                    disconnectedBufferOptions.isDeleteOldestMessages = false
                    mMqttClient?.setBufferOpts(disconnectedBufferOptions)
                    //subscribeTopic()
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    val defException = exception ?: RuntimeException("mqtt connection failure")
                    try {
                        mOnConnectListener?.onConnectFailure(defException)
                        PrintLog.e(mTag, "mqtt连接失败 : ${defException.cause}")
                    } catch (e: Exception) {

                    }
                }
            })

        } catch (e: Exception) {
            e.printStackTrace()
            mOnConnectListener?.onConnectFailure(e)
            PrintLog.e(mTag, "mqtt连接失败1 : ${e.cause}")
        }
    }

    override fun disconnect() {
        try {
            mMqttClient?.disconnect(null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    PrintLog.e(mTag, "断开成功 : success")
                    mOnDisconnectListener?.onDisconnectComplete("success")
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    PrintLog.e(mTag, "断开失败 : failure")
                    mOnDisconnectListener?.onDisconnectFailure("failure")
                }
            })
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun isConnected(): Boolean = mMqttClient != null && mMqttClient?.isConnected ?: false

    override fun subscribeTopic() {
        val list = mSubTopics
        // 没有可以订阅的主题
        if (list.isNullOrEmpty()) {
            return
        }
        if (mMqttClient == null) {
            return
        }
        try {
            list.forEach { topic ->
                mMqttClient?.subscribe(topic, 0, null, object : IMqttActionListener {
                    override fun onSuccess(asyncActionToken: IMqttToken?) {
                        PrintLog.v(mTag, "$topic 订阅成功")
                        mOnSubscribeListener?.onSubscribeSuccess(topic)
                    }

                    override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                        val defException = exception ?: RuntimeException("mqtt subscribe failure")
                        PrintLog.e(mTag, "$topic 订阅失败 : ${defException.cause}")
                        mOnSubscribeListener?.onSubscribeFailure(topic, defException)
                    }
                })
            }
        } catch (e: Exception) {
            e.printStackTrace()
            PrintLog.e(mTag, "订阅失败 : ${e.cause}")
            mOnSubscribeListener?.onSubscribeFailure("all", e)
        }
    }

    /** 订阅某一个主题 */
    override fun setStringSubTopic(topic: String) {
        // 没有可以订阅的主题
        if (topic.isEmpty()) {
            return
        }
        if (mMqttClient == null) {
            return
        }
        try {
            mMqttClient?.subscribe(topic, 0, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    // PrintLog.v(mTag, "$topic 订阅成功")
                    mOnSubscribeListener?.onSubscribeSuccess(topic)
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    val defException = exception ?: RuntimeException("mqtt subscribe failure")
                    //PrintLog.e(mTag, "$topic 订阅失败 : ${defException.cause}")
                    mOnSubscribeListener?.onSubscribeFailure(topic, defException)
                }
            })
        } catch (e: Exception) {
            e.printStackTrace()
            PrintLog.e(mTag, "订阅失败 : ${e.cause}")
            mOnSubscribeListener?.onSubscribeFailure("all", e)
        }
    }

    /** 退订某一个主题 */
    override fun unsubscribe(topic: String) {
        // 没有可以订阅的主题
        if (topic.isEmpty()) {
            return
        }
        if (mMqttClient == null) {
            return
        }
        mMqttClient?.unsubscribe(topic, null, object : IMqttActionListener {
            override fun onSuccess(asyncActionToken: IMqttToken) {
                PrintLog.v(mTag, "$topic 退订成功")
                mOnUnSubscribeListener?.unSubscribeSuccess(topic)
            }

            override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable?) {
                val defException = exception ?: RuntimeException("mqtt subscribe failure")
                PrintLog.e(mTag, "$topic 退订失败 : ${defException.cause}")
                mOnUnSubscribeListener?.unSubscribeFailure(topic, defException)
            }
        })
    }

    override fun setTag(tag: String) {
        if (tag.isNotEmpty()) {
            mTag = tag
        }
    }
}